/* 文档说明： */
/*  主要功能：协议和序列化反序列化的实现   */
#pragma once
#include <string>
#include <iostream>
#include <jsoncpp/json/json.h>

static const std::string blankspace_sep = " ";
static const std::string protocol_sep = "\n";

// 我们将添加报头的函数实现在类外：

//格式："len"\n"content"\n
bool Enpackage(const std::string& content, std::string *package) //函数作用，将一个字符串添加报头
{
    std::string temp;
    temp += std::to_string(content.size());
    temp += protocol_sep;
    temp += content;
    temp += protocol_sep;

    //*package = std::move(temp); //提高效率
    *package = temp;
    return true;
}

//格式："len"\n"content"\n
bool Depackage(std::string& package, std::string *content) //函数作用，将一个格式化的字符串去报头
{
    //找\n的位置
    //std::cout << "@" << package << std::endl;
    int pos1 = package.find(protocol_sep);
    if(pos1 == std::string::npos)
    {
        //std::cout << "&1";
        return false;
    }
    // int pos2 = package.find(protocol_sep, pos1 + 1); // json不适用：\r\n
    // if(pos2 == std::string::npos)
    // {
    //     //std::cout << "&2";
    //     return false;
    // }   

    std::string len_str = package.substr(0, pos1);
    //std::cout << "$" << len_str << std::endl;
    int len = std::stoi(len_str);
    int total_len = pos1 + len + 2;

    *content = package.substr(pos1 + 1, len); //从pos1 + 1位置开始，截取len个字符
    if(package.size() < pos1 + len + 2) //正确的报文长度应该“大于等于”格式的长度
    {
        //std::cout << (*content) << " " << (*content).size() << " ";
        //std::cout << "&3" << package.size() << " " << pos1 + len + 2;
        return false;
    }
    
    package.erase(0, total_len); //从0位置开始删除pos2 + 1个字符
    return true;
}



//格式："len"\n"10 + 10"\n
class Request
{
public:
    Request(int x, int y, char op)
    :_x(x), _y(y), _op(op)
    {}
    Request()
    {}
    ~Request()
    {}
public:
    bool Serialize(std::string *out) //序列化 输出型参数将结果带出 
    {
#ifdef Myself
        // 目标：将类对象的数据序列化
        std::string temp;
        temp += std::to_string(_x);
        temp += blankspace_sep;
        temp += _op;
        temp += blankspace_sep;
        temp += std::to_string(_y);

        *out = std::move(temp);
        return true;

#else
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["op"] = _op;

        Json::FastWriter w;
        //Json::StyledWriter w;
        *out = w.write(root);
        return true;
#endif
    }

    bool Deserialize(const std::string& in) //反序列化 —> 填写字段出一个对象
    {
#ifdef Myself
        //目标：将序列化的数据返回给类对象
        // "x op y"
        //先找到两个空格的位置
        int pos1 = in.find(blankspace_sep);
        if(pos1 == std::string::npos)
            return false;
        int pos2 = in.find(blankspace_sep, pos1 + 1); //从第一个空格的下一个位置开始找
        if(pos2 == std::string::npos)
            return false;
        
        //处理得到的位置信息
        _x = std::stoi(std::string(in.substr(0, pos1)));
        _op = in[pos1 + 1];
        _y = std::stoi(std::string(in.substr(pos2 + 1)));
        return true;
#else
        Json::Value v;
        Json::Reader r;
        r.parse(in, v);

        _x = v["x"].asInt();
        _y = v["y"].asInt();
        _op = v["op"].asInt();
        return true;
#endif
    }

public:
    void DebugPrint()
    {
        std::cout << "当前请求是：" << _x << _op << _y << std::endl;
    }

public:
    int _x;
    int _y;
    char _op;
};

//格式："len"\n"res code"\n
class Response
{
public:
    Response()
    {}
    Response(int res, int c)
    :_result(res), _exitcode(c)
    {}
    ~Response()
    {}
public:
    bool Serialize(std::string *out) //序列化
    {
#ifdef Myself
        std::string temp;
        temp += std::to_string(_result);
        temp += blankspace_sep;
        temp += std::to_string(_exitcode);

        *out = std::move(temp);
        return true;
#else
        Json::Value root;
        root["result"] = _result;
        root["code"] = _exitcode;

        Json::FastWriter w;
        *out = w.write(root);
        return true;
#endif
    }
    bool Deserialize(const std::string& in) //反序列化 —> 构造出一个对象
    {
#ifdef Myself
        //找位置
        int pos = in.find(blankspace_sep);
        if(pos == std::string::npos)
            return false;
        
        //分析数据
        _result = std::stoi(std::string(in.substr(0, pos)));
        _exitcode = std::stoi(std::string(in.substr(pos + 1)));
        return true;
#else 
        Json::Value v;
        Json::Reader r;
        r.parse(in, v);
        _result = v["result"].asInt();
        _exitcode = v["code"].asInt();
        return true;
#endif
    }
public:
    void DebugPrint()
    {
        std::cout << "计算结果为：" << _result << " code：" << _exitcode << std::endl;
    }
public:
    int _result;
    int _exitcode; //0代表结果正确，非0不正确
};